package com.stylefeng.sso.server.auth.service.impl;


import cn.hutool.core.convert.Convert;
import cn.stylefeng.roses.core.util.MD5Util;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.api.AuthService;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.stylefeng.sso.server.auth.service.TokenAuthService;
import com.stylefeng.sso.server.common.SsoSpringContextHolder;
import com.stylefeng.sso.server.constants.factory.ConstantFactory;
import com.stylefeng.sso.server.constants.factory.UserFactory;
import com.stylefeng.sso.server.modular.entity.User;
import com.stylefeng.sso.server.modular.mapper.MenuMapper;
import com.stylefeng.sso.server.modular.mapper.UserMapper;
import com.stylefeng.sso.server.modular.model.LoginUser;
import com.stylefeng.sso.server.modular.service.AdapterCache;
import com.stylefeng.sso.server.modular.service.DictService;
import com.stylefeng.sso.server.modular.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * auth服务接口最简单实现
 *
 * @author fengshuonan
 * @date 2018-02-03 22:56
 */
@Import({UserService.class})
@Service
public class TokenAuthServiceImpl implements TokenAuthService {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AdapterCache cache ;

    private Set<String> ssoClients = new HashSet<>();

    @Autowired
    private UserService userService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private DictService dictService;

    public static AuthService me() {
        return SsoSpringContextHolder.getBean(AuthService.class);
    }

    @Override
    public Integer checkUserLogin(String userName, String password) {
        User user = userService.getByAccount(userName);
        if (user != null) {
            //校验账号密码是否正确
            String md5Hex = MD5Util.encrypt(password + user.getSalt());
            if (md5Hex.equals(user.getPassword())) {
                return Math.toIntExact(user.getUserId());
            }
        }
        return null;
    }

    @Override
    public String createToken(Integer userId) {
        String token = IdWorker.get32UUID();
        LoginUser loginUserByUserId = this.getLoginUserByUserId(userId);
        cache.put(token, loginUserByUserId);
        return token;
    }

    @Override
    public boolean checkToken(HttpServletRequest request, String token, String clientAddr) {
        if (cache.containsKey(token)) {
            // 目前不需要记录客户端,20190426
//            recordSSOClient(clientAddr);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public LoginUser getLoginUserByToken(String token) {
        return (LoginUser) cache.get(token);
    }

    @Override
    public LoginUser getLoginUserByUserId(Integer userId) {

        User userInfo = userService.getById(userId);
        LoginUser loginUser=new LoginUser();
        loginUser.setPassword(userInfo.getPassword());
        loginUser.setAccount(userInfo.getAccount());
        loginUser.setAvatar(userInfo.getAvatar());
        loginUser.setDeptId(userInfo.getDeptId());
        loginUser.setEmail(userInfo.getEmail());
        loginUser.setId(userInfo.getUserId());
        loginUser.setName(userInfo.getName());
        return loginUser;

//        return sysUserService.getUserLoginInfo(userId);
    }

    @Override
    public void recordSSOClient(String clientAddr) {
        ssoClients.add(clientAddr);
    }

    @Override
    public Set<String> getAllSsoClientUrl() {
        return ssoClients;
    }

    @Override
    public Boolean removeCachedToken(String token) {
        try {
            cache.remove(token);
        }catch (Exception e){
            log.warn("退出的登录,清除redis中token失败",e);
            return false;
        }
        return true;
    }

    @Override
    public LoginUser user(String account) {

        User user = userMapper.getByAccount(account);

        LoginUser loginUser = UserFactory.createLoginUser(user);

        //用户角色数组
        Long[] roleArray = Convert.toLongArray(user.getRoleId());

        //如果角色是空就直接返回
        if (roleArray == null || roleArray.length == 0) {
            return loginUser;
        }

        //获取用户角色列表
        List<Long> roleList = new ArrayList<>();
        List<String> roleNameList = new ArrayList<>();
        List<String> roleTipList = new ArrayList<>();
        for (Long roleId : roleArray) {
            roleList.add(roleId);
            roleNameList.add(ConstantFactory.me().getSingleRoleName(roleId));
            roleTipList.add(ConstantFactory.me().getSingleRoleTip(Math.toIntExact(roleId)));
        }
        loginUser.setRoleList(roleList);
        loginUser.setRoleNames(roleNameList);
        loginUser.setRoleTips(roleTipList);

        //根据角色获取系统的类型
        List<String> systemTypes = this.menuMapper.getMenusTypesByRoleIds(roleList);

        //通过字典编码
        List<Map<String, Object>> dictsByCodes = dictService.getDictsByCodes(systemTypes);
        loginUser.setSystemTypes(dictsByCodes);

        //设置权限列表
        Set<String> permissionSet = new HashSet<>();
        for (Long roleId : roleList) {
            List<String> permissions = this.findPermissionsByRoleId(roleId);
            if (permissions != null) {
                for (String permission : permissions) {
                    if (ToolUtil.isNotEmpty(permission)) {
                        permissionSet.add(permission);
                    }
                }
            }
        }
        loginUser.setPermissions(permissionSet);

        return loginUser;
    }

    private List<String> findPermissionsByRoleId(Long roleId) {
        return menuMapper.getResUrlsByRoleId(Math.toIntExact(roleId));
    }
}
